/**
 * Created by chenweicheng on 8/3/2017.
 */
/**
 * Created by chenweicheng on 1/3/2017.
 */
/**
 * Created by Administrator on 2016/12/20 0020.
 */

import React, {Component} from 'react';
import {
    AppRegistry, View, Text, ScrollView, Image, StyleSheet, TouchableHighlight, NativeAppEventEmitter,
    Platform,
    PermissionsAndroid,
} from 'react-native';


var protobuf = require('protobufjs');
//import * as protobuf from "protobufjs";
import * as Long from "long"; // optional


var messages = require('../Babybath_pb');
var MessagesSnooker = require('../SnookerProto_pb');

// var textEncoding = require('text-encoding');
// var TextDecoder = textEncoding.TextDecoder;
// var TextEncoder = textEncoding.TextEncoder;

//var fs = require("fs");

import BleManager from '../BleManager';
import AssetsManager from '../AssetsManager';
var fs = require('react-native-fs');
export default class TestProtoManager extends Component {

    constructor(props) {
        super(props);
        this.state = {
            ble: null,
            connectState: 'disconnected',
        };

        this.scanning = false;

    }


    test_Proto() {

        string4 = "package myTest;\n" +
            "syntax = \"proto3\";\n" +
            "\n" +
            "message BabyBathMessage {\n" +
            "\tuint32 LoopCount = 1;\n" +
            " \tuint32 weight = 2;\n" +
            " \t\n" +
            "}";
        console.log('before load');//http://121.42.15.85:9000/Babybath.proto  ///storage/emulated/0/Babybath.proto  //'/storage/emulated/0/Download/Babybath.proto'
        protobuf.load(string4, function (err, root) {
                if (err)
                    throw err;

                // Obtain a messages type
                var BabyBathMessage = root.lookup("myTest.BabyBathMessage");

                // Create a new message
                var message = BabyBathMessage.create({weight: 10});

                // Verify the message if necessary (i.e. when possibly incomplete or invalid)
                var errMsg = BabyBathMessage.verify(message);
                if (errMsg)
                    throw Error(errMsg);

                // Encode a message to an Uint8Array (browser) or Buffer (node)
                var buffer = BabyBathMessage.encode(message).finish();
                // buffer.
                // ... do something with buffer
                console.log('encode buffer', buffer);

                // console.log('toString', buffer.);
                var message2 = BabyBathMessage.decode(buffer);
                // ... do something with message
                console.log('decode buffer', message2);
                // If your application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.
                // Or, encode a plain object
                var buffer1 = BabyBathMessage.encode({LoopCount: 3, weight: 10}).finish();
                // ... do something with buffer
                console.log('encode buffer', buffer1);
                // Decode an Uint8Array (browser) or Buffer (node) to a message
                var message3 = BabyBathMessage.decode(buffer1);
                // ... do something with message
                console.log('decode buffer', message3);
                // var message4 = BabyBathMessage.decode("831610");
                // ... do something with message
                //  console.log('decode buffer', message4);
                //'0': 8, '1': 3, '2': 16, '3': 10
                // const buf = new Buffer([0x08, 0x03, 0x10, 0x0a]);
                //     console.log('decode buffer', buf);


                var x = new Uint8Array([16, 10]);
                console.log('custom buffer decode buffer', BabyBathMessage.decode(x));
            }
        );

        // fs.readFileAssets('latticeConfig/Babybath.proto').then((string) => {
        //     console.log('readFileAssets', string)
        //     string2 = "package myTest;syntax = \"proto3\";//App向设备发送，循环从1~127. 设备收到数据后，回复app的数据LoopCount不变\n\t message BabyBathMessage {uint32 LoopCount = 1;uint32 weight = 2;}";
        //     string3 = "package myTest;\nsyntax = \"proto3\";\n\nmessage BabyBathMessage {\n\t\/\/设备主动发送，填0. \n\t\/\/App向设备发送，循环从1~127. 设备收到数据后，回复app的数据LoopCount不变\n\tuint32 LoopCount = 1;\n \tuint32 weight = 2;\n}";
        //     string4 = "package myTest;\n" +
        //         "syntax = \"proto3\";\n" +
        //         "\n" +
        //         "message BabyBathMessage {\n" +
        //         "\tuint32 LoopCount = 1;\n" +
        //         " \tuint32 weight = 2;\n" +
        //         " \t\n" +
        //         "}";
        //     console.log('before load');//http://121.42.15.85:9000/Babybath.proto  ///storage/emulated/0/Babybath.proto  //'/storage/emulated/0/Download/Babybath.proto'
        //     protobuf.load(string4, function (err, root) {
        //             if (err)
        //                 throw err;
        //
        //             // Obtain a messages type
        //             var BabyBathMessage = root.lookup("myTest.BabyBathMessage");
        //
        //             // Create a new message
        //             var message = BabyBathMessage.create({weight: 10});
        //
        //             // Verify the message if necessary (i.e. when possibly incomplete or invalid)
        //             var errMsg = BabyBathMessage.verify(message);
        //             if (errMsg)
        //                 throw Error(errMsg);
        //
        //             // Encode a message to an Uint8Array (browser) or Buffer (node)
        //             var buffer = BabyBathMessage.encode(message).finish();
        //             // buffer.
        //             // ... do something with buffer
        //             console.log('encode buffer', buffer);
        //
        //             // console.log('toString', buffer.);
        //             var message2 = BabyBathMessage.decode(buffer);
        //             // ... do something with message
        //             console.log('decode buffer', message2);
        //             // If your application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.
        //             // Or, encode a plain object
        //             var buffer1 = BabyBathMessage.encode({LoopCount: 3, weight: 10}).finish();
        //             // ... do something with buffer
        //             console.log('encode buffer', buffer1);
        //             // Decode an Uint8Array (browser) or Buffer (node) to a message
        //             var message3 = BabyBathMessage.decode(buffer1);
        //             // ... do something with message
        //             console.log('decode buffer', message3);
        //             // var message4 = BabyBathMessage.decode("831610");
        //             // ... do something with message
        //             //  console.log('decode buffer', message4);
        //             //'0': 8, '1': 3, '2': 16, '3': 10
        //             // const buf = new Buffer([0x08, 0x03, 0x10, 0x0a]);
        //             //     console.log('decode buffer', buf);
        //
        //
        //             var x = new Uint8Array([16, 10]);
        //             console.log('custom buffer decode buffer', BabyBathMessage.decode(x));
        //         }
        //     )
        // }, (error, string) => {
        //     console.log('readFileAssets error', string)
        // });

        // AssetsManager.getConfig("Babybath").then((string) => {
        //     console.log(string)
        //
        //
        //     console.log('before load');//http://121.42.15.85:9000/Babybath.proto  ///storage/emulated/0/Babybath.proto  //'/storage/emulated/0/Download/Babybath.proto'
        //     protobuf.load(string, function (err, root) {
        //             if (err)
        //                 throw err;
        //
        //             // Obtain a messages type
        //             var BabyBathMessage = root.lookup("myTest.BabyBathMessage");
        //
        //             // Create a new message
        //             var message = BabyBathMessage.create({weight: 10});
        //
        //             // Verify the message if necessary (i.e. when possibly incomplete or invalid)
        //             var errMsg = BabyBathMessage.verify(message);
        //             if (errMsg)
        //                 throw Error(errMsg);
        //
        //             // Encode a message to an Uint8Array (browser) or Buffer (node)
        //             var buffer = BabyBathMessage.encode(message).finish();
        //             // buffer.
        //             // ... do something with buffer
        //             console.log('encode buffer', buffer);
        //
        //             // console.log('toString', buffer.);
        //             var message2 = BabyBathMessage.decode(buffer);
        //             // ... do something with message
        //             console.log('decode buffer', message2);
        //             // If your application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.
        //             // Or, encode a plain object
        //             var buffer1 = BabyBathMessage.encode({LoopCount: 3, weight: 10}).finish();
        //             // ... do something with buffer
        //             console.log('encode buffer', buffer1);
        //             // Decode an Uint8Array (browser) or Buffer (node) to a message
        //             var message3 = BabyBathMessage.decode(buffer1);
        //             // ... do something with message
        //             console.log('decode buffer', message3);
        //             // var message4 = BabyBathMessage.decode("831610");
        //             // ... do something with message
        //             //  console.log('decode buffer', message4);
        //             //'0': 8, '1': 3, '2': 16, '3': 10
        //             // const buf = new Buffer([0x08, 0x03, 0x10, 0x0a]);
        //             //     console.log('decode buffer', buf);
        //
        //
        //             var x = new Uint8Array([16, 10]);
        //             console.log('custom buffer decode buffer', BabyBathMessage.decode(x));
        //         }
        //     )
        // }, (error) => {
        // })


    }


    headerType = {
        BabyBathMessage: 1,
        ReadyMessage: 2,
    };

    strAddHeader(str, headerType) {
        console.log("headerType=", headerType);
        switch (headerType) {

            case this.headerType.BabyBathMessage:
                console.log("headerType.BabyBathMessage");
                return "00" + str;

            case this.headerType.ReadyMessage:
                console.log("headerType.ReadyMessage");
                return "01" + str;
            default:
                return str;
        }
    }

    test_Proto2() {
        var message = new messages.BabyBathMessage();
        // message.setLoopcount(10);
        message.setWeight(3)
        console.log("serializeBinary", message.serializeBinary());
        console.log("deserializeBinary", messages.BabyBathMessage.deserializeBinary(message.serializeBinary()));


        text = message.serializeBinary().toString();
        console.log("text", text);
        //  console.log(this.uintToString(message.serializeBinary()));

        // var string = new TextDecoder("utf-8").decode(message.serializeBinary());
        // console.log("string", string);
        // var uint8array = new TextEncoder("utf-8").encode(string);
        // console.log("array", uint8array)

        //生成16进制命令并添加头，包括是否超过20个字符和messageid
        var snookerMessage = new MessagesSnooker.SnookerMessage();
        snookerMessage.setFollowingdist(333);
        console.log("serializeBinary", snookerMessage.serializeBinary());
        console.log(snookerMessage.serializeBinary()[0].toString(16));
        console.log(snookerMessage.serializeBinary()[1].toString(16));

        var string = "";
        for (var i = 0; i < snookerMessage.serializeBinary().length; i++) {
            console.log("The number is： " + snookerMessage.serializeBinary()[i].toString(16));
            string = string + this.formatStr(snookerMessage.serializeBinary()[i].toString(16));
        }
        console.log(string);
        string = this.strAddHeader(string, this.headerType.BabyBathMessage);
        console.log("add header==", string);


        console.log("deserializeBinary", MessagesSnooker.SnookerMessage.deserializeBinary(snookerMessage.serializeBinary()).array)
        var x = new Uint8Array([16, 205, 2]);
        console.log("customUintArray", MessagesSnooker.SnookerMessage.deserializeBinary(x).array);


        //去除header后解析
        console.log("before sub=", string);
        string = string.substr(2);
        console.log("after sub=", string);
        var y = new Uint8Array(string.length / 2);
        for (var i = 0; i < string.length / 2; i++) {
            console.log(string.substring(i * 2, (i + 1) * 2));
            y[i] = parseInt(string.substring(i * 2, (i + 1) * 2), 16);
        }
        // var y = new Uint8Array(string.length / 2 - 1);
        // for (var i = 0; i < string.length / 2 - 1; i++) {
        //     console.log(string.substring((i + 1) * 2, (i + 2) * 2));
        //     y[i] = parseInt(string.substring((i + 1) * 2, (i + 2) * 2), 16);
        // }
        console.log("custom y", y);
        console.log("customUintArray", MessagesSnooker.SnookerMessage.deserializeBinary(y).array);

    }

    formatStr(str) {
        if (str.length == 1) {
            return "0" + str
        } else {
            return str
        }
    }

    /*
     1.生成java可解析16进制字符串
     2、将1中16进制字符串翻转
     3、protobufjs支持本地proto文件

     */

    test_ProtoJs() {

        // var fs = require("fs");

        fs.readFile('/storage/emulated/0/Babybath.proto').then((string) => {
            console.log(string);
            protobuf.loadLocal("./Babybath.proto", string, function (err, root) {
                if (err)
                    throw err;

                // example code
                var BabyBathMessage = root.lookupType("BabyBathMessage");
                var message = BabyBathMessage.create({weight: 10});
                var buffer = BabyBathMessage.encode(message).finish();
                console.log("buffer", buffer)

            });
        }, (error, string) => {
            console.log(error, string);
        });
        // console.log(userProtoStr);


        // protobuf.load("Babybath.proto")
        //     .then(function (root) {
        //     });
        // var Root = protobuf.Root,
        //     Type = protobuf.Type,
        //     Field = protobuf.Field;
        // var BabyBathMessage = new Type("BabyBathMessage").add(new Field("weight", 1, "uint32"));
        // var root = new Root().define("myTest").add(BabyBathMessage);
        //
        //
        // var message = BabyBathMessage.create({weight: 10});
        // var buffer = BabyBathMessage.encode(message).finish();
        // console.log("buffer", buffer)
    }

    componentDidMount() {

        BleManager.start({showAlert: true}).then(() => {
            console.log("start successss:");
            //检查蓝牙开关
            BleManager.checkState();
        }, (error) => {
            console.log("start fail" + error);
        });
        if (Platform.OS === 'android') {
            //发现设备广播
            this.handleDiscoverPeripheral = NativeAppEventEmitter
                .addListener('BleManagerDiscoverPeripheral', this.handleDiscoverPeripheral.bind(this));
            //连接设备成功广播
            this.handleConnectedPeripheral = NativeAppEventEmitter
                .addListener('BleManagerConnectPeripheral', this.handleConnectedPeripheral.bind(this));
            //断开连接成功广播
            this.handleDisConnectedPeripheral = NativeAppEventEmitter
                .addListener('BleManagerDisconnectPeripheral', this.handleDisConnectedPeripheral.bind(this));
            //收到数据广播
            this.handleNotification = NativeAppEventEmitter
                .addListener('BleManagerDidUpdateValueForCharacteristic', this.handleNotification.bind(this));
            this.handleBleManagerDidUpdateState = NativeAppEventEmitter
                .addListener('BleManagerDidUpdateState', this.handleBleManagerDidUpdateState.bind(this));
        } else {
            //发现设备广播
            this.handleDiscoverPeripheral = myNativeEvt
                .addListener('BleManagerDiscoverPeripheral', this.handleDiscoverPeripheral.bind(this));
            //连接设备成功广播
            this.handleConnectedPeripheral = myNativeEvt
                .addListener('BleManagerConnectPeripheral', this.handleConnectedPeripheral.bind(this));
            //断开连接成功广播
            this.handleDisConnectedPeripheral = myNativeEvt
                .addListener('BleManagerDisconnectPeripheral', this.handleDisConnectedPeripheral.bind(this));
            //收到数据广播
            this.handleNotification = myNativeEvt
                .addListener('BleManagerDidUpdateValueForCharacteristic', this.handleNotification.bind(this));
            this.handleBleManagerDidUpdateState = myNativeEvt
                .addListener('BleManagerDidUpdateState', this.handleBleManagerDidUpdateState.bind(this));
        }

        if (Platform.OS === 'android' && Platform.Version >= 23) {
            PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION).then((result) => {
                if (result) {
                    console.log("Permission is OK");
                } else {
                    PermissionsAndroid.requestPermission(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION).then((result) => {
                        if (result) {
                            console.log("User accept");
                        } else {
                            console.log("User refuse");
                        }
                    });
                }
            });
        }
        this.startScan(true)


    }

    static componentWillUnmount() {
        //反注册广播
        NativeAppEventEmitter.removeAllListeners();
    }

    handleConnect(data) {

        BleManager.connect(data['id']).then((map) => {
            this.handleStartNotification(this.state.ble);
        }, (error) => {
            console.log("connect fail");
            console.log(error);

        });
    }

    handleStartNotification(data) {
        BleManager.setNotification(data['id']).then(
            () => {
                console.log('start notification success')
            },
            (error) => {
                console.log('start notification fail', error)
            });
    }

    handleDiscoverPeripheral(data) {
        if (data['name'] == null) {

        } else {
            var name = data['name'];
            var fdStart = name.indexOf("SmartUp");
            if (fdStart == 0) {
                // 表示strCode是以ssss开头；
                clearInterval(this.scanId);
                this.scanning = false;
                this.setState({ble: data});
                this.handleConnect(this.state.ble)
            } else if (fdStart == -1) {
                //  表示strCode不是以ssss开头
                console.log('handleDiscoverPeripheral')

            }
        }
    }

    handleConnectedPeripheral(data) {
        this.setState({connectState: 'connected'});
    }

    handleDisConnectedPeripheral(data) {
        this.setState({connectState: 'disconnected'});
        this.startScan(true);
        // alert('糟糕，断开了')
    }

    handleNotification(data) {

        console.log('handleNotification', data);

    }

    handleBleManagerDidUpdateState(data) {
        if (data['state'] == "on") {
        } else if (data['state'] == "off") {
            this.setState({connectState: 'disconnected'});
            BleManager.enableBluetooth().then(() => {
                console.log('BLE 开关打开成功',);
            }, (result) => {
                console.log('BLE 开关打开失败', result);
            });
        }

    }

    startScan(bool) {
        if (bool) {
            this.scanning = true;
            this.scanId = setInterval(() => this.handleScan(), 5000);
        } else {
            this.scanning = false;
            clearInterval(this.scanId);
            BleManager.stopScan().then(() => {
                console.log('stop scan success')
            }, (error) => {
                console.log('stop scan fail')
            })

        }
    }

    handleScan() {
        BleManager.scan(3, 'SmartUp+')
            .then(() => {
                //  console.log('Scanning.Success..')
            }, (error) => {
                //    console.log('Scanning...fail')
            });
    }

    handleWriteBack(ble, data) {


        BleManager.writeBack(ble['id'], data).then((map) => {
            console.log("handleWriteBack..success");
            console.log(map)
        }, (error) => {
            console.log("handleWriteBack..fail");
            console.log(error)
        })
    }

    render() {
        return (
            <View style={styles.container}>
                <TouchableHighlight style={{padding: 20, backgroundColor: '#ccc'}}
                                    onPress={() =>this.test_Proto()  }>
                    <Text>Protobufjs_decodeio</Text>
                </TouchableHighlight>
                <TouchableHighlight style={{padding: 20, backgroundColor: '#ccc'}}
                                    onPress={() =>this.test_Proto2()  }>
                    <Text>protobuf_google</Text>
                </TouchableHighlight>
                <TouchableHighlight style={{padding: 20, backgroundColor: '#ccc'}}
                                    onPress={() =>this.test_ProtoJs()  }>
                    <Text>protobufjs2</Text>
                </TouchableHighlight>
                <TouchableHighlight style={{padding: 20, backgroundColor: '#ccc'}}
                                    onPress={() =>this.handleWriteBack(this.state.ble,'aac8b0a318593647fd24d6')  }>
                    <Text>handleWriteBack</Text>
                </TouchableHighlight>
            </View>
        );
    }
}
//aac8b0a318593647fd24d6  ///aac8b0a718593647fd2422
var styles = StyleSheet.create({
    container: {
        //   justifyContent: 'center',
        flex: 1,
        flexDirection: 'column',//没有flexDirection这个属性的话，justifyContent不会生效
        justifyContent: 'center',
        padding: 15,
        alignItems: 'center'
    }
});
AppRegistry.registerComponent('TestProtoManager', () => TestProtoManager);